From afe3cf62fc93f345a50debe3844e0fc7241c8700 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 24 Mar 2005 17:22:38 +0000 Subject: [PATCH] bitkeeper revision 1.1236.43.1 (4242f75e6Zk-5XZxY7UL-J_Qi8D43g) Fix VIRQ_TIMER holdoff for SMP guests. Signed-off-by: Keir Fraser --- .../arch/xen/i386/kernel/time.c | 18 +++---- xen/arch/ia64/patch/linux-2.6.7/time.c | 4 +- xen/arch/x86/time.c | 16 +++--- xen/common/sched_atropos.c | 4 +- xen/common/sched_bvt.c | 4 +- xen/common/sched_rrobin.c | 4 +- xen/common/schedule.c | 53 ++++++++++++------- xen/include/xen/sched-if.h | 40 ++++++-------- xen/include/xen/sched.h | 1 + xen/include/xen/time.h | 6 +-- 10 files changed, 76 insertions(+), 74 deletions(-) diff --git a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c index 92610b2356..d0dec7f85f 100644 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c @@ -672,6 +672,7 @@ int set_timeout_timer(void) { u64 alarm = 0; int ret = 0; + unsigned long j; #ifdef CONFIG_SMP unsigned long seq; #endif @@ -685,13 +686,14 @@ int set_timeout_timer(void) #ifdef CONFIG_SMP do { seq = read_seqbegin(&xtime_lock); - if (smp_processor_id()) - alarm = __jiffies_to_st(jiffies + 1); - else - alarm = __jiffies_to_st(jiffies + 1); + j = jiffies + 1; + alarm = __jiffies_to_st(j); } while (read_seqretry(&xtime_lock, seq)); #else - alarm = __jiffies_to_st(next_timer_interrupt()); + j = next_timer_interrupt(); + if (j < (jiffies + 1)) + j = jiffies + 1; + alarm = __jiffies_to_st(j); #endif /* Failure is pretty bad, but we'd best soldier on. */ @@ -726,7 +728,6 @@ void time_resume(void) } #ifdef CONFIG_SMP -#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg) static irqreturn_t local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -764,11 +765,6 @@ static irqreturn_t local_timer_interrupt(int irq, void *dev_id, #endif } - if (smp_processor_id() == 0) { - xxprint("bug bug\n"); - BUG(); - } - return IRQ_HANDLED; } diff --git a/xen/arch/ia64/patch/linux-2.6.7/time.c b/xen/arch/ia64/patch/linux-2.6.7/time.c index d0b421fb67..cf77d6905a 100644 --- a/xen/arch/ia64/patch/linux-2.6.7/time.c +++ b/xen/arch/ia64/patch/linux-2.6.7/time.c @@ -70,11 +70,11 @@ + return now; +} + -+int update_dom_time(struct exec_domain *ed) ++void update_dom_time(struct exec_domain *ed) +{ +// FIXME: implement this? +// printf("update_dom_time: called, not implemented, skipping\n"); -+ return 0; ++ return; +} + +/* Set clock to after 00:00:00 UTC, 1 January, 1970. */ diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 208945ca33..2ad8395446 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -296,18 +296,16 @@ static inline void __update_dom_time(struct exec_domain *ed) spin_unlock(&d->time_lock); } -int update_dom_time(struct exec_domain *ed) +void update_dom_time(struct exec_domain *ed) { unsigned long flags; - if ( ed->domain->shared_info->tsc_timestamp == full_tsc_irq ) - return 0; - - read_lock_irqsave(&time_lock, flags); - __update_dom_time(ed); - read_unlock_irqrestore(&time_lock, flags); - - return 1; + if ( ed->domain->shared_info->tsc_timestamp != full_tsc_irq ) + { + read_lock_irqsave(&time_lock, flags); + __update_dom_time(ed); + read_unlock_irqrestore(&time_lock, flags); + } } /* Set clock to after 00:00:00 UTC, 1 January, 1970. */ diff --git a/xen/common/sched_atropos.c b/xen/common/sched_atropos.c index ec24c03fe2..9b7c071b16 100644 --- a/xen/common/sched_atropos.c +++ b/xen/common/sched_atropos.c @@ -325,7 +325,7 @@ static void block(struct domain* sdom) /** * ATROPOS - main scheduler function */ -task_slice_t ksched_scheduler(s_time_t time) +struct task_slice ksched_scheduler(s_time_t time) { struct domain *cur_sdom = current; /* Current sdom */ s_time_t newtime; @@ -335,7 +335,7 @@ task_slice_t ksched_scheduler(s_time_t time) struct at_dom_info *cur_info; static unsigned long waitq_rrobin = 0; int i; - task_slice_t ret; + struct task_slice ret; cur_info = DOM_INFO(cur_sdom); diff --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index 3b91b2a9ab..65fa6125bf 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -363,7 +363,7 @@ static int bvt_adjdom( * i.e., the domain with lowest EVT. * The runqueue should be ordered by EVT so that is easy. */ -static task_slice_t bvt_do_schedule(s_time_t now) +static struct task_slice bvt_do_schedule(s_time_t now) { struct domain *d; struct exec_domain *prev = current, *next = NULL, *next_prime, *ed; @@ -375,7 +375,7 @@ static task_slice_t bvt_do_schedule(s_time_t now) struct bvt_edom_info *p_einf = NULL; struct bvt_edom_info *next_einf = NULL; struct bvt_edom_info *next_prime_einf = NULL; - task_slice_t ret; + struct task_slice ret; ASSERT(prev->ed_sched_priv != NULL); ASSERT(prev_einf != NULL); diff --git a/xen/common/sched_rrobin.c b/xen/common/sched_rrobin.c index cfc30c11a1..a3535ae128 100644 --- a/xen/common/sched_rrobin.c +++ b/xen/common/sched_rrobin.c @@ -99,11 +99,11 @@ static int rr_init_idle_task(struct domain *d) } /* Main scheduling function */ -static task_slice_t rr_do_schedule(s_time_t now) +static struct task_slice rr_do_schedule(s_time_t now) { struct domain *prev = current; int cpu = current->processor; - task_slice_t ret; + struct task_slice ret; if ( !is_idle_task(prev) ) { diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 562daa6132..761f636a75 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -13,6 +13,15 @@ * */ +/*#define WAKE_HISTO*/ +/*#define BLOCKTIME_HISTO*/ + +#if defined(WAKE_HISTO) +#define BUCKETS 31 +#elif defined(BLOCKTIME_HISTO) +#define BUCKETS 200 +#endif + #include #include #include @@ -31,15 +40,6 @@ static char opt_sched[10] = "bvt"; string_param("sched", opt_sched); -/*#define WAKE_HISTO*/ -/*#define BLOCKTIME_HISTO*/ - -#if defined(WAKE_HISTO) -#define BUCKETS 31 -#elif defined(BLOCKTIME_HISTO) -#define BUCKETS 200 -#endif - #define TIME_SLOP (s32)MICROSECS(50) /* allow time to slip a bit */ /* @@ -66,7 +66,7 @@ static void t_timer_fn(unsigned long unused); static void dom_timer_fn(unsigned long data); /* This is global for now so that private implementations can reach it */ -schedule_data_t schedule_data[NR_CPUS]; +struct schedule_data schedule_data[NR_CPUS]; extern struct scheduler sched_bvt_def; // extern struct scheduler sched_rrobin_def; @@ -371,7 +371,7 @@ void __enter_scheduler(void) struct exec_domain *prev = current, *next = NULL; int cpu = prev->processor; s_time_t now; - task_slice_t next_slice; + struct task_slice next_slice; s32 r_time; /* time for new dom to run */ perfc_incrc(sched_run); @@ -446,9 +446,15 @@ void __enter_scheduler(void) TRACE_2D(TRC_SCHED_SWITCH, next->domain->id, next); + prev->sleep_tick = schedule_data[cpu].tick; + /* Ensure that the domain has an up-to-date time base. */ - if ( !is_idle_task(next->domain) && update_dom_time(next) ) - send_guest_virq(next, VIRQ_TIMER); + if ( !is_idle_task(next->domain) ) + { + update_dom_time(next); + if ( next->sleep_tick != schedule_data[cpu].tick ) + send_guest_virq(next, VIRQ_TIMER); + } context_switch(prev, next); } @@ -468,7 +474,7 @@ int idle_cpu(int cpu) * - dom_timer: per domain timer to specifiy timeout values ****************************************************************************/ -/* The scheduler timer: force a run through the scheduler*/ +/* The scheduler timer: force a run through the scheduler */ static void s_timer_fn(unsigned long unused) { TRACE_0D(TRC_SCHED_S_TIMER_FN); @@ -476,20 +482,26 @@ static void s_timer_fn(unsigned long unused) perfc_incrc(sched_irq); } -/* Periodic tick timer: send timer event to current domain*/ +/* Periodic tick timer: send timer event to current domain */ static void t_timer_fn(unsigned long unused) { - struct exec_domain *ed = current; + struct exec_domain *ed = current; + unsigned int cpu = ed->processor; TRACE_0D(TRC_SCHED_T_TIMER_FN); - if ( !is_idle_task(ed->domain) && update_dom_time(ed) ) + schedule_data[cpu].tick++; + + if ( !is_idle_task(ed->domain) ) + { + update_dom_time(ed); send_guest_virq(ed, VIRQ_TIMER); + } page_scrub_schedule_work(); - t_timer[ed->processor].expires = NOW() + MILLISECS(10); - add_ac_timer(&t_timer[ed->processor]); + t_timer[cpu].expires = NOW() + MILLISECS(10); + add_ac_timer(&t_timer[cpu]); } /* Domain timer function, sends a virtual timer interrupt to domain */ @@ -498,7 +510,8 @@ static void dom_timer_fn(unsigned long data) struct exec_domain *ed = (struct exec_domain *)data; TRACE_0D(TRC_SCHED_DOM_TIMER_FN); - (void)update_dom_time(ed); + + update_dom_time(ed); send_guest_virq(ed, VIRQ_TIMER); } diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h index f73eace25b..c9fdd23702 100644 --- a/xen/include/xen/sched-if.h +++ b/xen/include/xen/sched-if.h @@ -1,36 +1,31 @@ -#include - -/* +/****************************************************************************** * Additional declarations for the generic scheduler interface. This should * only be included by files that implement conforming schedulers. * * Portions by Mark Williamson are (C) 2004 Intel Research Cambridge */ -#define BUCKETS 10 +#ifndef __XEN_SCHED_IF_H__ +#define __XEN_SCHED_IF_H__ -typedef struct schedule_data_st -{ - spinlock_t schedule_lock; /* spinlock protecting curr pointer - TODO check this */ - struct exec_domain *curr; /* current task */ - struct exec_domain *idle; /* idle task for this cpu */ - void * sched_priv; - struct ac_timer s_timer; /* scheduling timer */ +struct schedule_data { + spinlock_t schedule_lock; /* spinlock protecting curr */ + struct exec_domain *curr; /* current task */ + struct exec_domain *idle; /* idle task for this cpu */ + void *sched_priv; + struct ac_timer s_timer; /* scheduling timer */ + unsigned long tick; /* current periodic 'tick' */ #ifdef BUCKETS u32 hist[BUCKETS]; /* for scheduler latency histogram */ #endif -} __cacheline_aligned schedule_data_t; - +} __cacheline_aligned; -typedef struct task_slice_st -{ +struct task_slice { struct exec_domain *task; s_time_t time; -} task_slice_t; +}; -struct scheduler -{ +struct scheduler { char *name; /* full name for this scheduler */ char *opt_name; /* option name for this scheduler */ unsigned int sched_id; /* ID for this scheduler */ @@ -44,7 +39,7 @@ struct scheduler void (*sleep) (struct exec_domain *); void (*wake) (struct exec_domain *); void (*do_block) (struct exec_domain *); - task_slice_t (*do_schedule) (s_time_t); + struct task_slice (*do_schedule) (s_time_t); int (*control) (struct sched_ctl_cmd *); int (*adjdom) (struct domain *, struct sched_adjdom_cmd *); @@ -53,7 +48,6 @@ struct scheduler int (*prn_state) (int); }; -/* per CPU scheduler information */ -extern schedule_data_t schedule_data[]; - +extern struct schedule_data schedule_data[]; +#endif /* __XEN_SCHED_IF_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 44f24831e8..861f1a24a0 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -73,6 +73,7 @@ struct exec_domain #endif struct ac_timer timer; /* one-shot timer for timeout values */ + unsigned long sleep_tick; /* tick at which this vcpu started sleep */ s_time_t lastschd; /* time this domain was last scheduled */ s_time_t lastdeschd; /* time this domain was last descheduled */ diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h index b1eeade753..104b611212 100644 --- a/xen/include/xen/time.h +++ b/xen/include/xen/time.h @@ -54,9 +54,9 @@ s_time_t get_s_time(void); #define MILLISECS(_ms) (((s_time_t)(_ms)) * 1000000ULL ) #define MICROSECS(_us) (((s_time_t)(_us)) * 1000ULL ) -extern int update_dom_time(struct exec_domain *ed); -extern void do_settime(unsigned long secs, unsigned long usecs, - u64 system_time_base); +extern void update_dom_time(struct exec_domain *ed); +extern void do_settime( + unsigned long secs, unsigned long usecs, u64 system_time_base); #endif /* __XEN_TIME_H__ */ -- 2.30.2